﻿#ifndef _NETPCAP_H_
#define _NETPCAP_H_


#ifdef __unix__
#include <arpa/inet.h>
#endif

#include <cstring>
#include <memory>
#include <vector>
#include <thread>
#include <chrono>
#include <functional>
#include <unordered_map>
#include <map>
#include <mutex>
#include <pcap.h>
#include <atomic>
#include <list>
#include "mlogger.hpp"
#include "netpcap_def.h"

#ifdef WIN32
#if !defined(DLL_STATIC)
#ifdef _DLL_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#else
#define DLL_EXPORT
#endif
#else
#define DLL_EXPORT
#endif

/*Windows DLL导出尽最大限度使用基础类型,避免导出STL复杂数据结构 */
#ifdef WIN32
#pragma warning(push)
#pragma warning(disable: 4251)
#endif

namespace secsmart_pcap
{
    class netpcap_mgr;
    class netpcap_worker;
    class netpcap_file;

    using pcapmgr_sptr      = std::shared_ptr<netpcap_mgr>;
    using pcapworker_sptr   = std::shared_ptr<netpcap_worker>;
    #define FILE_BUFF_SIZE       (1<<20)   
    #define FILE_BUFF_SHDR       (1<<16)
    /**
    * @brief 单个线程的包具体处理
    *
    */
    class netpcap_worker : public std::enable_shared_from_this<netpcap_worker>
    {
        public:
            static void                     worker_handler(unsigned char*, const struct pcap_pkthdr*, const unsigned char*);
            void                            worker_run();
            void                            worker_stop();
            void                            worker_set_stop();
            void                            worker_get_stat(pcap_pkt_stat_t *pkt_stat, struct pcap_stat *dev_stat);
            void                            worker_set_pcap_filter(const std::string &filter_string);
        public:
            std::atomic_bool                m_is_running_;
            std::shared_ptr<std::thread>    m_thread_sptr_;
            cap_task_t                      m_task_info_;
            pcap_pkt_stat_t                 m_pkt_stat;
        public:
            netpcap_worker() : m_dev_handle_(nullptr), m_pcap_dumper_(nullptr), m_pcap_file_(nullptr) {};
            ~netpcap_worker() { worker_close_device(); };
            netpcap_worker(const netpcap_worker&) = delete;
            netpcap_worker& operator=(const netpcap_worker&) = delete;
        private:
            pcap_t*                         m_dev_handle_;
            pcap_dumper_t*                  m_pcap_dumper_;  // pcap dumper
            netpcap_file*                   m_pcap_file_;    // 抓包存储的文件
            int                             m_link_type_;

            bool                            worker_init();
            bool                            worker_open_device();
            bool                            worker_open_pcapfile();
            void                            worker_close_device();
            void                            worker_write_pcapfile_init();
            void                            worker_write_pcapfile(const pcap_pkthdr *header, const unsigned char *pkt_data);
            void                            worker_clean_stat();
    };
    
    class DLL_EXPORT netpcap_mgr
    {
        public:
            bool                        init(spdlogger_sptr logger);
            void                        uninit();
            void                        config_update(){};
            bool                        log_ctrl(std::uint32_t level, bool funcEnable);
            std::uint32_t               log_get_module_level();
        public:
            bool                        pcap_task_start(cap_task_t& pcapTasker);
            bool                        pcap_task_start_replay(cap_task_t& pcapTasker);
            bool                        pcap_task_stop(const std::string& taskName);
            bool                        pcap_task_list(std::vector<std::string>& taskList);
            bool                        pcap_task_query(const std::string& taskName, cap_task_info_t& state);
            bool                        pcap_task_stop_all();
            bool                        pcap_device_netaddr_lookup(const std::string& device, std::string& netaddr);
            bool                        pcap_ifnames_get(std::vector<std::string>& devLists);
            bool                        pcap_ifinfos_get(std::vector<ifinfo_sptr>& ifLists);
            void                        pcap_app_dir_get(std::string& dirPath);
            void                        pcap_task_get_stat(const std::string& taskName, pcap_pkt_stat_t &pkt_stat, pcap_stat &dev_stat);
            void                        pcap_task_get_stat_all(pcap_pkt_stat_t &pkt_stat, pcap_stat &dev_stat);
            void                        pcap_task_set_filter(const std::string& task_name, const std::string &filter_string);
        private:
            bool                        task_map_add(const std::string& taskName, pcapworker_sptr workerSptr);
            bool                        task_map_del(const std::string& taskName);
            bool                        task_map_query(const std::string& taskName, cap_task_info_t& taskInfo);
            bool                        task_map_clear();
        private:
            std::unordered_map<std::string, pcapworker_sptr>    m_task_map_;
            std::mutex                                          m_task_map_lock_;
        public:
            netpcap_mgr() {};
            ~netpcap_mgr() { uninit(); };
            netpcap_mgr(const netpcap_mgr&) = delete;
            netpcap_mgr& operator=(const netpcap_mgr&) = delete;
    };
}

#ifdef WIN32
#pragma warning(pop)
#endif

#endif

